#include "type.h"
#include "message.h"
#include "protect.h"
/*--------------------extern fun-----------------------------*/
void disp_int(int);
void dispStr(char*);
void schedule(void); //来自clock.c 中的进程调度
u32	seg2phys(struct descriptor*);

/*------------------------------------------------------------*/

/*---------------------interface-----------------------------*/
//添加消息到信箱中
void bind_msg(struct process* proc,Message* msg);
//从信箱中删除消息
Message* unbind_msg(struct process* proc);
//搜索进程 
struct process* find_process(int id);
/*------------------------------------------------------------*/

//发送消息函数
//发送后该进程阻塞 
void send1(struct process* cur,Message* msg){
	struct process* proc;
	msg->p_src=(cur-p_process); //设置消息的源进程pid
	proc=find_process(msg->p_dest);//根据消息的目的进程pid查找对应进程结构

	if(!proc){
		dispStr("err for router\n");
	}else{
		if(proc->state==BLOCK){ //如果目的进程是阻塞态
			proc->state=READY;	//则唤醒该进程
			bind_msg(proc,msg);//将消息加入信箱
			cur->state=BLOCK;  //设置该进程阻塞
			block_arrange();//将当前进程移动链表尾
		}else{
		//如果目的进程不是阻塞态
		//将消息加入信箱
		//并设置该进程阻塞
			bind_msg(proc,msg);
			cur->state=BLOCK;
			block_proc();
		}
	}
}

//接受消息函数
//如果信箱为空 则阻塞该进程
void receive1(struct process* cur,Message* msg){
	struct process* p_src; //源进程指针
	Message* msg1;
	msg1=unbind_msg(cur); //从信箱取出消息
	if(msg1==NUL_MSG){ //如果信箱为空 则阻塞该进程
			cur->state=BLOCK;	
			//该进程状态为阻塞态 调用进程调度算法
			//调度下一就绪进程
			schedule();
			return;
	}else{
	/**
	*从信箱中将消息拷贝到该进程的数据空间
	**/
	u32 dest;
	u32 src;
	/**
	*将目的进程的虚地址转换为物理地址
	**/
	dest=vir2phys(seg2phys(&cur->ldt[1]),msg); 

	//找到发送消息的进程
	if(!(p_src=find_process(msg1->p_src))){
		dispStr("error");
		return;
	}	
	/**
	*将源进程的虚地址转换为物理地址
	**/
	src=vir2phys(seg2phys(&p_src->ldt[1]),msg1);
	/**
	*msg1 为源地址
	*addr 为目的地址
	**/
	memcpy(dest,src,sizeof(Message));
	}
}

//从消息链表中删除消息 并返回该消息
Message* unbind_msg(struct process* proc){
	Message* msg;
	msg=proc->mail_box;
	if(msg==NUL_MSG)  //如果链表为空
		return NUL_MSG; //返回空消息
	else{
		proc->mail_box=msg->next;//将信箱链接到下一个消息
		msg->next=NUL_MSG;//将消息的下一个链接设置为空
		return msg;
	}
}

//将消息加进该进程的信箱中
void bind_msg(struct process* proc,Message* msg){
/**
*每个进程有一个信箱 消息间用链表链接起来
**/
	Message* m2;
	Message* m1;
	m1=proc->mail_box;
	m2=NUL_MSG;

	//采用先来服务算法
	while(m1!=NUL_MSG){
		m2=m1;
		m1=m1->next;
	}
	if(m2==NUL_MSG){  //如果链表为空
		proc->mail_box=msg;//设置新消息
	}else{
		m2->next=msg;//将新消息加到链表中
	}
	msg->next=NUL_MSG;
}

//根据进程id查找进程
struct process* find_process(int pid){
	if(pid<0 || pid>MAX_NUM-1)
		return NULL_PROC;
	else{
		return p_process+pid;
	}
}
